﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FW
{
    public class Busca
    {

        public String Metaphone(String strTag)
        {

            String strRetorno="";
            strTag = strTag.Replace("\t", " ");
            strTag = strTag.Replace("\r", " ");
            strTag = strTag.Replace("\n", " ");
            strTag = strTag.Replace("  ", " ");
            strTag = strTag.Trim();
            char[] chaSeparador = " ".ToCharArray();
            String[] strLista = strTag.Split(chaSeparador);
            String strVolta = "";
            int intPosicao;
            int intTamanhoTag;
            int intPosicaoFinal;
            String strOriginal;
            String strCaraterAtual;
            //for (int i=0; i < strLista.Length; i++)
            //{
            //    if (strLista[i]=="") strLista.Remove(i);
            //}
            foreach (String lstValor in strLista)
            {
                /*
                 *    inicializa a chave metafônica
                 */
                
                strVolta = "";
                //cleanup
                strOriginal = lstValor.Trim().ToUpper();
                /*
                 *    coloca a posição no começo
                 */
                intPosicao = 0;

                ///*
                // *    recupera o tamanho máximo da string
                // */
                //intTamanhoTag = strOriginal.Length;

                ///*
                // *    configura o final da string
                // */
                //intPosicaoFinal = intTamanhoTag-1;
                //strOriginal=strTag."    "; ???????????????????

                /*
                 *    vamos repor alguns caracteres portugueses facilmente
                 *    confundidos, substituíndo os números não confundir com
                 *    os encontros consonantais (RR), dígrafos (LH, NH) e o
                 *    C-cedilha:
                 *
                 *    "LH" to "1"
                 *    "RR" to "2"
                 *    "NH" to "3"
                 *    "Ç"  to "SS"
                 *    "CH" to "X"
                 */
                strOriginal = SubstituiValores(strOriginal, "1|2|3|4|5|6|7|8|9|0", " ");
                strOriginal = SubstituiValores(strOriginal, "Ã|Á|Â", "A");
                strOriginal = SubstituiValores(strOriginal, "É|Ê", "E");
                strOriginal = SubstituiValores(strOriginal, "Í|Y", "I");
                strOriginal = SubstituiValores(strOriginal, "Õ|Ó|Ô", "O");
                strOriginal = SubstituiValores(strOriginal, "Ú|Ü", "U");
                strOriginal = SubstituiValores(strOriginal, "ç", "SS");
                strOriginal = SubstituiValores(strOriginal, "Ç", "SS");

                /*
                 *    faz substituições
                 *    -> "olho", "ninho", "carro", "exceção", "cabaça"
                 */
                strOriginal = SubstituiValores(strOriginal, "LH", "1");
                strOriginal = SubstituiValores(strOriginal, "NH", "3");
                strOriginal = SubstituiValores(strOriginal, "RR", "2");
                strOriginal = SubstituiValores(strOriginal, "XC", "SS");
                /*
                 *    a correção do SCH e do TH por conta dos nomes próprios:
                 *    -> "schiffer", "theodora", "ophelia", etc..
                 *
                 */
                strOriginal = SubstituiValores(strOriginal, "SCH", "X");
                strOriginal = SubstituiValores(strOriginal, "TH", "T");
                strOriginal = SubstituiValores(strOriginal, "PH", "F");

                intPosicao = 0;
                while (intPosicao < strOriginal.Length)

                {
                    /*
                    *    recupera o tamanho máximo da string
                    */
                    intTamanhoTag = strOriginal.Length;

                    /*
                     *    configura o final da string
                     */
                    intPosicaoFinal = intTamanhoTag - 1;
                    
                    
                    /*
                     *    pega um caracter da string
                     */
                    strCaraterAtual = strOriginal.Substring(intPosicao, 1);

                    /*
                     *    se é uma vogal e faz parte do começo da string,
                     *    coloque-a como parte da metachave
                     */
                    if (eh_Vogal(strOriginal, intPosicao) && intPosicao == 0)
                    {
                        strVolta += strCaraterAtual;
                        intPosicao += 1;
                    }
                    /*
                     *    procurar por consoantes que tem um único som, ou que
                     *    que já foram substituídas ou soam parecido, como
                     *     "Ç" para "SS" e "NH" para "1"
                     */
                    else
                    {
                        if (string_at(strOriginal, intPosicao, 1, "1|2|3|B|D|F|J|K|L|M|P|T|V"))
                        {
                            strVolta += strCaraterAtual;

                            /*
                            *    incrementar por 2 se uma letra repetida for encontrada
                            */
                            if (intPosicao < intPosicaoFinal  && strOriginal.Substring(intPosicao + 1, 1) == strCaraterAtual)
                            {
                                intPosicao += 2;
                            }
                            else
                                /*
                                 *    senão incrementa em 1
                                 */
                                intPosicao += 1;
                        }
                        else
                        {
                            /*
                            *    checar consoantes com som confuso e similar
                            */
                            switch (strCaraterAtual)
                            {

                                case "G":
                                    if (intPosicao < intPosicaoFinal)
                                    {
                                        switch (strOriginal.Substring(intPosicao + 1, 1))
                                        {
                                            case "E":
                                            case "I":
                                                strVolta += "J";
                                                intPosicao += 2;
                                                break;

                                            case "U":
                                                strVolta += "G";
                                                intPosicao += 2;

                                                break;

                                            case "R":
                                                strVolta += "GR";
                                                intPosicao += 2;
                                                break;

                                            default:
                                                strVolta += "G";
                                                intPosicao += 1;
                                                break;
                                        }
                                    }    
                                    else                                        
                                    {                                                
                                        strVolta += "G";
                                        intPosicao += 1;
                                    }
                                    break;    

                                case "U":
                                    if (intPosicao>0 &&  eh_Vogal(strOriginal, intPosicao - 1))
                                    {
                                        intPosicao += 1;
                                        strVolta += "L";
                                    }
                                    else
                                    {   /*
                                    *    senão...
                                    */
                                        intPosicao += 1;
                                    }
                                    break;
                                case "R":
                                    if (intPosicao == 0 || intPosicao == intPosicaoFinal)
                                    {
                                        intPosicao += 1;
                                        strVolta += "2";
                                        break;
                                    }
                                    else
                                    {
                                        if (eh_Vogal(strOriginal, intPosicao - 1) && eh_Vogal(strOriginal, intPosicao + 1))
                                        {
                                            intPosicao += 1;
                                            strVolta += "R";
                                        }
                                        else
                                        {
                                            if (!eh_Vogal(strOriginal, intPosicao - 1))
                                            {
                                                intPosicao += 1;
                                                strVolta += "R";
                                            }
                                            else
                                            {
                                                /*
                                                 *    senão...
                                                 */
                                                intPosicao += 1;
                                                strVolta += "2";
                                            }
                                        }
                                        break;
                                    }


                                case "Z":
                                    if (intPosicao >= (strOriginal.Length - 1))
                                    {
                                        intPosicao += 1;
                                        strVolta += "S";
                                    }
                                    else
                                    {
                                        if (intPosicao < intPosicaoFinal &&   strOriginal.Substring(intPosicao + 1, 1) == "Z")
                                        {
                                            strVolta += "Z";
                                            intPosicao += 2;
                                        }
                                        else
                                        {
                                            /*
                                         *    senão...
                                         */
                                            intPosicao += 1;
                                            strVolta += "Z";
                                        }

                                    }
                                    break;
                                case "N":
                                    if (intPosicao >= (strOriginal.Length - 1))
                                    {
                                        strVolta += "M";
                                        intPosicao += 1;
                                    }
                                    else
                                    {
                                        if (intPosicao<intPosicaoFinal && strOriginal.Substring(intPosicao + 1, 1) == "N")
                                        {
                                            strVolta += "N";
                                            intPosicao += 2;
                                        }
                                        else
                                        {
                                            /*
                                             *    senão...
                                             */
                                            strVolta += "N";
                                            intPosicao += 1;
                                        }
                                    }
                                    break;
                                case "S":
                                    /*
                                     *    caso especial "assado", "posse", "sapato", "sorteio"
                                     */
                                    if (intPosicao == intPosicaoFinal 
                                        || (intPosicao<intPosicaoFinal && strOriginal.Substring(intPosicao + 1, 1) == "S"))
                                    {
                                        strVolta += "S";
                                        intPosicao += 2;
                                    }
                                    else
                                    {
                                        if ((intPosicao == 0))
                                        {
                                            strVolta += "S";
                                            intPosicao += 1;
                                        }
                                        else
                                        {
                                            if (intPosicao !=0 
                                                && intPosicao!=intPosicaoFinal 
                                                && eh_Vogal(strOriginal, intPosicao - 1) 
                                                &&eh_Vogal(strOriginal, intPosicao + 1))
                                            {

                                                strVolta += "Z";
                                                intPosicao += 1;
                                            }

                                            else
                                            {
                                                /*
                                                *  Ex.: Ascender, Lascivia
                                                */
                                                if (
                                                            intPosicao <= intPosicaoFinal-2 &&
                                                            (strOriginal.Substring(intPosicao + 1, 1) == "C") &&
                                                            (
                                                                (strOriginal.Substring(intPosicao + 2, 1) == "E") ||
                                                                (strOriginal.Substring(intPosicao + 2, 1) == "I")
                                                            )
                                                       )
                                                {
                                                    strVolta += "S";
                                                    intPosicao += 3;
                                                }
                                                else
                                                {
                                                    /*
                                                * Ex.: Asco, Auscutar, Mascavo
                                                */
                                                    if (
                                                                intPosicao <= intPosicaoFinal - 2 &&
                                                                (strOriginal.Substring(intPosicao + 1, 1) == "C") &&
                                                                (
                                                                    (strOriginal.Substring(intPosicao + 2, 1) == "A") ||
                                                                    (strOriginal.Substring(intPosicao + 2, 1) == "O") ||
                                                                    (strOriginal.Substring(intPosicao + 2, 1) == "U")
                                                                )
                                                           )
                                                    {
                                                        strVolta += "SC";
                                                        intPosicao += 3;
                                                    }
                                                    else
                                                    {
                                                        strVolta += "S";
                                                        intPosicao += 1;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    break;
                                case "X":
                                    /*
                                     *    caso especial "táxi", "axioma", "axila", "tóxico"
                                     */
                                    if (intPosicao == 1 && strOriginal.Substring(intPosicao - 1, 1) == "E" )
                                    {
                                        strVolta += "Z";
                                        intPosicao += 1;
                                    }
                                    else
                                    {
                                        if (intPosicao == 1 && strOriginal.Substring(intPosicao - 1, 1) == "I" )
                                        {
                                            strVolta += "X";
                                            intPosicao += 1;
                                        }
                                        else
                                        {
                                            if (intPosicao ==1 && (eh_Vogal(strOriginal, intPosicao - 1)) )
                                            {
                                                strVolta += "KS";
                                                intPosicao += 1;
                                            }
                                            else
                                            {
                                                strVolta += "X";
                                                intPosicao += 1;
                                            }

                                        }
                                    }
                                    break;
                                case "C":
                                    /*
                                     *    caso especial "cinema", "cereja"
                                     */
                                    if (string_at(strOriginal, intPosicao, 2, "CE|CI"))
                                    {
                                        strVolta += "S";
                                        intPosicao += 2;
                                    }
                                    else
                                    {
                                        if (intPosicao<intPosicaoFinal && strOriginal.Substring(intPosicao + 1, 1) == "H")
                                        {
                                            strVolta += "X";
                                            intPosicao += 2;
                                        }
                                        else
                                        {
                                            strVolta += "K";
                                            intPosicao += 1;
                                        }
                                    }
                                    break;
                                /*
                                 *    como a letra "h" é silenciosa no português, vamos colocar
                                 *    a chave meta como a vogal logo após a letra "h"
                                 */
                                case "H":
                                    if (intPosicao < intPosicaoFinal && eh_Vogal(strOriginal, intPosicao + 1))
                                    {
                                        strVolta += strOriginal[intPosicao + 1];
                                        intPosicao += 2;
                                    }
                                    else
                                    {
                                        intPosicao += 1;
                                    }
                                    break;

                                case "Q":
                                    if (intPosicao<intPosicaoFinal && strOriginal.Substring(intPosicao + 1, 1) == "U")
                                    {
                                        intPosicao += 2;
                                    }
                                    else
                                    {
                                        intPosicao += 1;
                                    }

                                    strVolta += "K";
                                    break;

                                case "W":
                                    if (intPosicao < intPosicaoFinal && eh_Vogal(strOriginal, intPosicao + 1))
                                    {
                                        strVolta += "V";
                                        intPosicao += 2;
                                    }
                                    else
                                    {
                                        strVolta += "U";
                                        intPosicao += 2;
                                    }
                                    break;

                                //default:
                                default:
                                    intPosicao += 1;
                                    break;
                            }
                        }
                    }

                }
                /*
             *    corta os caracteres em branco
             */
                strVolta = strVolta.Trim();
                strRetorno += strVolta + " ";
            }
            /*
             *    retorna a chave matafônica
             */
            
            return strRetorno.Trim();
        }

        private static String SubstituiValores(String strValor, String strValoresSubstituir, String strSubstituirPor)
        {
            String strVolta = strValor.Trim();
            char[] chaSeparador = "|".ToCharArray();
            String[] strListaSubstituir = strValoresSubstituir.Split(chaSeparador);
            foreach (String lstValor in strListaSubstituir)
            {
                strVolta = strVolta.Replace(lstValor, strSubstituirPor);
            }
            return strVolta;
        }

        private static Boolean eh_Vogal(string strValor, int intPosicao)
        {

            if ("AEIOU".IndexOf(strValor.Substring(intPosicao, 1), 0) >= 0)
            {
                return true;
            }
            else
            {
                return false;
            };
        }

        private static Boolean string_at(String STRING, int START, int STRING_LENGTH, String LIST)
        {
            if ((START < 0) || ((START + STRING_LENGTH-1) > STRING.Length - 1))
            {
                return false;
            }
            char[] chaSeparador = "|".ToCharArray();
            String[] aLIST = LIST.Split(chaSeparador);
            for (int I = 0; I < aLIST.Length; I++)
            {
                if (aLIST[I] == STRING.Substring(START, STRING_LENGTH))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
